﻿using System.IO;
using System.Text;
using System.Net;
using System.Xml;

using ECCIT;

namespace ECCIT.Net.SAML2
{
    public static class SAMLIdentifiers
    {
        // Nested Types
        public static class ActionNamespaces
        {
            // Fields
            public const string GHPP = "urn:oasis:names:tc:SAML:1.0:action:ghpp";
            public const string RWEDC = "urn:oasis:names:tc:SAML:1.0:action:rwedc";
            public const string RWEDCWithNegation = "urn:oasis:names:tc:SAML:1.0:action:rwedc-negation";
            public const string Unix = "urn:oasis:names:tc:SAML:1.0:action:unix";
        }

        public static class Actions
        {
            // Fields
            public const string Control = "Control";
            public const string Delete = "Delete";
            public const string Execute = "Execute";
            public const string GET = "GET";
            public const string HEAD = "HEAD";
            public const string NotControl = "~Control";
            public const string NotDelete = "~Delete";
            public const string NotExecute = "~Execute";
            public const string NotRead = "~Read";
            public const string NotWrite = "~Write";
            public const string POST = "POST";
            public const string PUT = "PUT";
            public const string Read = "Read";
            public const string Write = "Write";
        }

        public static class AttributeNameFormats
        {
            // Fields
            public const string Basic = "urn:oasis:names:tc:SAML:2.0:attrname-format:basic";
            public const string Unspecified = "urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified";
            public const string URI = "urn:oasis:names:tc:SAML:2.0:attrname-format:uri";
        }

        public static class AuthnContextClasses
        {
            // Fields
            public const string AuthenticatedTelephony = "urn:oasis:names:tc:SAML:2.0:ac:classes:AuthenticatedTelephony";
            public const string InternetProtocol = "urn:oasis:names:tc:SAML:2.0:ac:classes:InternetProtocol";
            public const string InternetProtocolPassword = "urn:oasis:names:tc:SAML:2.0:ac:classes:InternetProtocolPassword";
            public const string Kerberos = "urn:oasis:names:tc:SAML:2.0:ac:classes:Kerberos";
            public const string MobileOneFactorContract = "urn:oasis:names:tc:SAML:2.0:ac:classes:MobileOneFactorContract";
            public const string MobileOneFactorUnregistered = "urn:oasis:names:tc:SAML:2.0:ac:classes:MobileOneFactorUnregistered";
            public const string MobileTwoFactorContract = "urn:oasis:names:tc:SAML:2.0:ac:classes:MobileTwoFactorContract";
            public const string MobileTwoFactorUnregistered = "urn:oasis:names:tc:SAML:2.0:ac:classes:MobileTwoFactorUnregistered";
            public const string NomadTelephony = "urn:oasis:names:tc:SAML:2.0:ac:classes:NomadTelephony";
            public const string Password = "urn:oasis:names:tc:SAML:2.0:ac:classes:Password";
            public const string PasswordProtectedTransport = "urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport";
            public const string PersonalTelephony = "urn:oasis:names:tc:SAML:2.0:ac:classes:PersonalTelephony";
            public const string PGP = "urn:oasis:names:tc:SAML:2.0:ac:classes:PGP";
            public const string PreviousSession = "urn:oasis:names:tc:SAML:2.0:ac:classes:PreviousSession";
            public const string SecureRemotePassword = "urn:oasis:names:tc:SAML:2.0:ac:classes:SecureRemotePassword";
            public const string Smartcard = "urn:oasis:names:tc:SAML:2.0:ac:classes:Smartcard";
            public const string SmartcardPKI = "urn:oasis:names:tc:SAML:2.0:ac:classes:SmartcardPKI";
            public const string SoftwarePKI = "urn:oasis:names:tc:SAML:2.0:ac:classes:SoftwarePKI";
            public const string SPKI = "urn:oasis:names:tc:SAML:2.0:ac:classes:SPKI";
            public const string Telephony = "urn:oasis:names:tc:SAML:2.0:ac:classes:Telephony";
            public const string TimeSyncToken = "urn:oasis:names:tc:SAML:2.0:ac:classes:TimeSyncToken";
            public const string TLSClient = "urn:oasis:names:tc:SAML:2.0:ac:classes:TLSClient";
            public const string Unspecified = "urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified";
            public const string X509 = "urn:oasis:names:tc:SAML:2.0:ac:classes:X509";
            public const string XMLDSig = "urn:oasis:names:tc:SAML:2.0:ac:classes:XMLDSig";
        }

        public static class AuthnContextComparison
        {
            // Fields
            public const string Better = "better";
            public const string Exact = "exact";
            public const string Maximum = "maximum";
            public const string Minimum = "minimum";
        }

        public static class AuthzDecision
        {
            // Fields
            public const string Deny = "Deny";
            public const string Indeterminate = "Indeterminate";
            public const string Permit = "Permit";
        }

        public enum Binding
        {
            Unspecified,
            SOAP,
            PAOS,
            HTTPRedirect,
            HTTPPost,
            HTTPArtifact,
            URI
        }

        public static class BindingURIs
        {
            // Fields
            public const string HTTPArtifact = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact";
            public const string HTTPPost = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST";
            public const string HTTPRedirect = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect";
            public const string PAOS = "urn:oasis:names:tc:SAML:2.0:bindings:PAOS";
            public const string SOAP = "urn:oasis:names:tc:SAML:2.0:bindings:SOAP";
            public const string URI = "urn:oasis:names:tc:SAML:2.0:bindings:URI";

            // Methods
            public static string BindingToURI(SAMLIdentifiers.Binding binding)
            {
                switch (binding)
                {
                    case SAMLIdentifiers.Binding.SOAP:
                        return "urn:oasis:names:tc:SAML:2.0:bindings:SOAP";

                    case SAMLIdentifiers.Binding.PAOS:
                        return "urn:oasis:names:tc:SAML:2.0:bindings:PAOS";

                    case SAMLIdentifiers.Binding.HTTPRedirect:
                        return "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect";

                    case SAMLIdentifiers.Binding.HTTPPost:
                        return "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST";

                    case SAMLIdentifiers.Binding.HTTPArtifact:
                        return "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact";

                    case SAMLIdentifiers.Binding.URI:
                        return "urn:oasis:names:tc:SAML:2.0:bindings:URI";
                }
                throw new SAMLBindingException("The binding is invalid: " + binding);
            }

            public static SAMLIdentifiers.Binding URIToBinding(string bindingURI)
            {
                switch (bindingURI)
                {
                    case "urn:oasis:names:tc:SAML:2.0:bindings:SOAP":
                        return SAMLIdentifiers.Binding.SOAP;

                    case "urn:oasis:names:tc:SAML:2.0:bindings:PAOS":
                        return SAMLIdentifiers.Binding.PAOS;

                    case "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect":
                        return SAMLIdentifiers.Binding.HTTPRedirect;

                    case "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST":
                        return SAMLIdentifiers.Binding.HTTPPost;

                    case "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact":
                        return SAMLIdentifiers.Binding.HTTPArtifact;

                    case "urn:oasis:names:tc:SAML:2.0:bindings:URI":
                        return SAMLIdentifiers.Binding.URI;
                }
                throw new SAMLBindingException("The binding is invalid: " + bindingURI);
            }
        }

        public static class ConsentIdentifiers
        {
            // Fields
            public const string Explicit = "urn:oasis:names:tc:SAML:2.0:consent:current-explicit";
            public const string Implicit = "urn:oasis:names:tc:SAML:2.0:consent:current-implicit";
            public const string Inapplicable = "urn:oasis:names:tc:SAML:2.0:consent:inapplicable";
            public const string Obtained = "urn:oasis:names:tc:SAML:2.0:consent:obtained";
            public const string Prior = "urn:oasis:names:tc:SAML:2.0:consent:prior";
            public const string Unavailable = "urn:oasis:names:tc:SAML:2.0:consent:unavailable";
            public const string Unspecified = "urn:oasis:names:tc:SAML:2.0:consent:unspecified";
        }

        public static class NameIdentifierFormats
        {
            // Fields
            public const string EmailAddress = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress";
            public const string Entity = "urn:oasis:names:tc:SAML:2.0:nameid-format:entity";
            public const string Kerberos = "urn:oasis:names:tc:SAML:2.0:nameid-format:kerberos";
            public const string Persistent = "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent";
            public const string Transient = "urn:oasis:names:tc:SAML:2.0:nameid-format:transient";
            public const string Unspecified = "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified";
            public const string WindowsDomainQualifiedName = "urn:oasis:names:tc:SAML:1.1:nameid-format:WindowsDomainQualifiedName";
            public const string X509SubjectName = "urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName";
        }

        public static class PrimaryStatusCodes
        {
            // Fields
            public const string Requester = "urn:oasis:names:tc:SAML:2.0:status:Requester";
            public const string Responder = "urn:oasis:names:tc:SAML:2.0:status:Responder";
            public const string Success = "urn:oasis:names:tc:SAML:2.0:status:Success";
            public const string VersionMismatch = "urn:oasis:names:tc:SAML:2.0:status:VersionMismatch";
        }

        public enum Profile
        {
            Unspecified,
            SSOBrowser,
            SSOECP,
            SSOLogout,
            NameIDManagement,
            Artifact,
            Query,
            NameIDMapping,
            BasicAttribute,
            X500,
            UUID,
            DCE,
            XACML
        }

        public static class ProfileURIs
        {
            // Fields
            public const string Artifact = "urn:oasis:names:tc:SAML:2.0:profiles:artifact";
            public const string BasicAttribute = "urn:oasis:names:tc:SAML:2.0:profiles:attribute:basic";
            public const string DCE = "urn:oasis:names:tc:SAML:2.0:profiles:attribute:DCE";
            public const string NameIDManagement = "urn:oasis:names:tc:SAML:2.0:profiles:SSO:nameid-mgmt";
            public const string NameIDMapping = "urn:oasis:names:tc:SAML:2.0:profiles:nameidmapping";
            public const string Query = "urn:oasis:names:tc:SAML:2.0:profiles:query";
            public const string SSOBrowser = "urn:oasis:names:tc:SAML:2.0:profiles:SSO:browser";
            public const string SSOECP = "urn:oasis:names:tc:SAML:2.0:profiles:SSO:ecp";
            public const string SSOLogout = "urn:oasis:names:tc:SAML:2.0:profiles:SSO:logout";
            public const string UUID = "urn:oasis:names:tc:SAML:2.0:profiles:attribute:UUID";
            public const string X500 = "urn:oasis:names:tc:SAML:2.0:profiles:attribute:X500";
            public const string XACML = "urn:oasis:names:tc:SAML:2.0:profiles:attribute:XACML";

            // Methods
            public static string ProfileToURI(SAMLIdentifiers.Profile profile)
            {
                switch (profile)
                {
                    case SAMLIdentifiers.Profile.SSOBrowser:
                        return "urn:oasis:names:tc:SAML:2.0:profiles:SSO:browser";

                    case SAMLIdentifiers.Profile.SSOECP:
                        return "urn:oasis:names:tc:SAML:2.0:profiles:SSO:ecp";

                    case SAMLIdentifiers.Profile.SSOLogout:
                        return "urn:oasis:names:tc:SAML:2.0:profiles:SSO:logout";

                    case SAMLIdentifiers.Profile.NameIDManagement:
                        return "urn:oasis:names:tc:SAML:2.0:profiles:SSO:nameid-mgmt";

                    case SAMLIdentifiers.Profile.Artifact:
                        return "urn:oasis:names:tc:SAML:2.0:profiles:artifact";

                    case SAMLIdentifiers.Profile.Query:
                        return "urn:oasis:names:tc:SAML:2.0:profiles:query";

                    case SAMLIdentifiers.Profile.NameIDMapping:
                        return "urn:oasis:names:tc:SAML:2.0:profiles:nameidmapping";

                    case SAMLIdentifiers.Profile.BasicAttribute:
                        return "urn:oasis:names:tc:SAML:2.0:profiles:attribute:basic";

                    case SAMLIdentifiers.Profile.X500:
                        return "urn:oasis:names:tc:SAML:2.0:profiles:attribute:X500";

                    case SAMLIdentifiers.Profile.UUID:
                        return "urn:oasis:names:tc:SAML:2.0:profiles:attribute:UUID";

                    case SAMLIdentifiers.Profile.DCE:
                        return "urn:oasis:names:tc:SAML:2.0:profiles:attribute:DCE";

                    case SAMLIdentifiers.Profile.XACML:
                        return "urn:oasis:names:tc:SAML:2.0:profiles:attribute:XACML";
                }
                throw new SAMLProfileException("The profile is invalid");
            }

            public static SAMLIdentifiers.Profile URIToProfile(string profileURI)
            {
                switch (profileURI)
                {
                    case "urn:oasis:names:tc:SAML:2.0:profiles:SSO:browser":
                        return SAMLIdentifiers.Profile.SSOBrowser;

                    case "urn:oasis:names:tc:SAML:2.0:profiles:SSO:ecp":
                        return SAMLIdentifiers.Profile.SSOECP;

                    case "urn:oasis:names:tc:SAML:2.0:profiles:SSO:logout":
                        return SAMLIdentifiers.Profile.SSOLogout;

                    case "urn:oasis:names:tc:SAML:2.0:profiles:SSO:nameid-mgmt":
                        return SAMLIdentifiers.Profile.NameIDManagement;

                    case "urn:oasis:names:tc:SAML:2.0:profiles:artifact":
                        return SAMLIdentifiers.Profile.Artifact;

                    case "urn:oasis:names:tc:SAML:2.0:profiles:query":
                        return SAMLIdentifiers.Profile.Query;

                    case "urn:oasis:names:tc:SAML:2.0:profiles:nameidmapping":
                        return SAMLIdentifiers.Profile.NameIDMapping;

                    case "urn:oasis:names:tc:SAML:2.0:profiles:attribute:basic":
                        return SAMLIdentifiers.Profile.BasicAttribute;

                    case "urn:oasis:names:tc:SAML:2.0:profiles:attribute:X500":
                        return SAMLIdentifiers.Profile.X500;

                    case "urn:oasis:names:tc:SAML:2.0:profiles:attribute:UUID":
                        return SAMLIdentifiers.Profile.UUID;

                    case "urn:oasis:names:tc:SAML:2.0:profiles:attribute:DCE":
                        return SAMLIdentifiers.Profile.DCE;

                    case "urn:oasis:names:tc:SAML:2.0:profiles:attribute:XACML":
                        return SAMLIdentifiers.Profile.XACML;
                }
                throw new SAMLProfileException("The profile URI is invalid");
            }
        }

        public static class SecondaryStatusCodes
        {
            // Fields
            public const string AuthnFailed = "urn:oasis:names:tc:SAML:2.0:status:AuthnFailed";
            public const string InvalidAttrNameOrValue = "urn:oasis:names:tc:SAML:2.0:status:InvalidAttrNameOrValue";
            public const string InvalidNameIDPolicy = "urn:oasis:names:tc:SAML:2.0:status:urn:oasis:names:tc:SAML:2.0:status:InvalidNameIDPolicy";
            public const string NoAuthnContext = "urn:oasis:names:tc:SAML:2.0:status:NoAuthnContext";
            public const string NoAvailableIDP = "urn:oasis:names:tc:SAML:2.0:status:NoAvailableIDP";
            public const string NoPassive = "urn:oasis:names:tc:SAML:2.0:status:NoPassive";
            public const string NoSupportedIDP = "urn:oasis:names:tc:SAML:2.0:status:NoSupportedIDP";
            public const string PartialLogout = "urn:oasis:names:tc:SAML:2.0:status:PartialLogout";
            public const string ProxyCountExceeded = "urn:oasis:names:tc:SAML:2.0:status:ProxyCountExceeded";
            public const string RequestDenied = "urn:oasis:names:tc:SAML:2.0:status:RequestDenied";
            public const string RequestUnsupported = "urn:oasis:names:tc:SAML:2.0:status:RequestUnsupported";
            public const string RequestVersionDeprecated = "urn:oasis:names:tc:SAML:2.0:status:RequestVersionDeprecated";
            public const string RequestVersionTooHigh = "urn:oasis:names:tc:SAML:2.0:status:RequestVersionTooHigh";
            public const string RequestVersionTooLow = "urn:oasis:names:tc:SAML:2.0:status:RequestVersionTooLow";
            public const string ResourceNotRecognized = "urn:oasis:names:tc:SAML:2.0:status:ResourceNotRecognized";
            public const string TooManyResponses = "urn:oasis:names:tc:SAML:2.0:status:TooManyResponses";
            public const string UnknownAttrProfile = "urn:oasis:names:tc:SAML:2.0:status:UnknownAttrProfile";
            public const string UnknownPrincipal = "urn:oasis:names:tc:SAML:2.0:status:UnknownPrincipal";
            public const string UnsupportedBinding = "urn:oasis:names:tc:SAML:2.0:status:UnsupportedBinding";
        }

        public static class SubjectConfirmationMethods
        {
            // Fields
            public const string Bearer = "urn:oasis:names:tc:SAML:2.0:cm:bearer";
            public const string HolderOfKey = "urn:oasis:names:tc:SAML:2.0:cm:holder-of-key";
            public const string SenderVouches = "urn:oasis:names:tc:SAML:2.0:cm:sender-vouches";
        }
    }
}
